#ifndef MANAGER_H
#define MANAGER_H

#include <map>
#include <vector>
#include <wx/event.h>
#include <wx/cmdline.h>
#include "sdk_events.h"
#include "M_Code_functor.h"
#include "M_Code_exception.h"

class wxFrame;
class wxWindow;
class ProjectManager;
class EditorManager;
class DebuggerManager;
class LogManager;
class PluginManager;
class ToolsManager;
class MacrosManager;
class PersonalityManager;
class wxMenu;
class wxMenuBar;
class wxToolBar;
class UserVariableManager;
class ScriptingManager;
class ConfigManager;
class FileManager;
class ColourManager;
class CCManager;
class cbSearchResultsLog;

class Manager {
    wxFrame* m_pAppWindow;
    wxToolBar* toolbar;
    static bool m_AppShuttingDown;
    static bool m_AppStartedUp;
    static bool m_BlockYields;
    static bool m_IsBatch;
    static wxCmdLineParser m_CmdLineParser;
    Manager();
    ~Manager();
    void OnMenu( wxCommandEvent& event );
  public:
    static void SetAppStartedUp( bool app_started_up );
    static void SetAppShuttingDown( bool app_shutting_down );
    static void SetBatchBuild( bool is_batch );
    static bool IsBatchBuild() { return m_IsBatch; }
    static void BlockYields( bool block );
    static void Yield();
    static void ProcessPendingEvents();
    static void Shutdown();
    bool ProcessEvent( CodeBlocksEvent& event );
    bool ProcessEvent( CodeBlocksDockEvent& event );
    bool ProcessEvent( CodeBlocksLayoutEvent& event );
    bool ProcessEvent( CodeBlocksLogEvent& event );
    static Manager* Get();
    static void Free();
    wxFrame*  GetAppFrame() const;
    wxWindow* GetAppWindow() const;
    static bool IsAppShuttingDown();
    static bool IsAppStartedUp();
    ProjectManager* GetProjectManager() const;
    EditorManager* GetEditorManager() const;
    LogManager* GetLogManager() const;
    PluginManager* GetPluginManager() const;
    ToolsManager* GetToolsManager() const;
    MacrosManager* GetMacrosManager() const;
    PersonalityManager* GetPersonalityManager() const;
    UserVariableManager* GetUserVariableManager() const;
    ScriptingManager* GetScriptingManager() const;
    ConfigManager* GetConfigManager( const wxString& name_space ) const;
    FileManager* GetFileManager() const;
    DebuggerManager* GetDebuggerManager() const;
    ColourManager* GetColourManager() const;
    CCManager* GetCCManager() const;
    static void InitXRC( bool force = false );
    static void LoadXRC( wxString relpath );
    static bool LoadResource( const wxString& file );
    static wxMenuBar* LoadMenuBar( wxString resid, bool createonfailure = false );
    static wxMenu* LoadMenu( wxString menu_id, bool createonfailure = false );
    static wxToolBar* LoadToolBar( wxFrame *parent, wxString resid, bool defaultsmall = true );
    static Manager* Get( wxFrame* appWindow );
    wxToolBar* CreateEmptyToolbar();
    wxToolBar* GetMinToolbar();
    static void AddonToolBar( wxToolBar* toolBar, wxString resid );
    static wxCmdLineParser* GetCmdLineParser();
    void RegisterEventSink( wxEventType eventType, IEventFunctorBase<CodeBlocksEvent>* functor );
    void RegisterEventSink( wxEventType eventType, IEventFunctorBase<CodeBlocksDockEvent>* functor );
    void RegisterEventSink( wxEventType eventType, IEventFunctorBase<CodeBlocksLayoutEvent>* functor );
    void RegisterEventSink( wxEventType eventType, IEventFunctorBase<CodeBlocksLogEvent>* functor );
    void RemoveAllEventSinksFor( void* owner );
    cbSearchResultsLog* GetSearchResultLogger() const { return m_SearchResultLog; }
    void SetSearchResultLogger( cbSearchResultsLog *log ) { m_SearchResultLog = log; }
  private:
    typedef std::vector< IEventFunctorBase<CodeBlocksEvent>* > EventSinksArray;
    typedef std::map< wxEventType, EventSinksArray > EventSinksMap;
    typedef std::vector< IEventFunctorBase<CodeBlocksDockEvent>* > DockEventSinksArray;
    typedef std::map< wxEventType, DockEventSinksArray > DockEventSinksMap;
    typedef std::vector< IEventFunctorBase<CodeBlocksLayoutEvent>* > LayoutEventSinksArray;
    typedef std::map< wxEventType, LayoutEventSinksArray > LayoutEventSinksMap;
    typedef std::vector< IEventFunctorBase<CodeBlocksLogEvent>* > LogEventSinksArray;
    typedef std::map< wxEventType, LogEventSinksArray > LogEventSinksMap;
    EventSinksMap m_EventSinks;
    DockEventSinksMap m_DockEventSinks;
    LayoutEventSinksMap m_LayoutEventSinks;
    LogEventSinksMap m_LogEventSinks;
    cbSearchResultsLog *m_SearchResultLog;
};

template <class MgrT> class Mgr {
    static MgrT *instance;
    static bool isShutdown;
    explicit Mgr( const Mgr<MgrT>& ) { ; };
    Mgr<MgrT>& operator=( Mgr<MgrT> const& ) { ; };
  protected:
    Mgr() { assert( Mgr<MgrT>::instance == nullptr ); }
    virtual ~Mgr() { Mgr<MgrT>::instance = nullptr; }
  public:
    static bool Valid() { return instance; }
    static MgrT* Get() {
      if( instance == nullptr ) {
        if( isShutdown == false ) {
          instance = new MgrT();
        } else {
          cbAssert( "在子系统关闭后调用get是一个错误!" );
        }
      }
      return instance;
    }
    static void Free() {
      isShutdown = true;
      delete instance;
      instance = nullptr;
    }
};

#endif
